home *** CD-ROM | disk | FTP | other *** search
- /*
-
- GOAL:
- This program is intended to read CD audio data into a disk file.
-
- Author:
- Yeng-Chee Su (yenchee@csie.nctu.edu.tw)
- Department of Computer Science and Information Engineering
- National Chiao Tung University
- &
- Klaas Hemstra (hst@mh.nl)
- Gouda, the Netherlands
-
- Notice:
- Most CD-ROM drive doesn't have the capability to read raw
- data on compact disk, but some drives can work. These includes
- Panasonic CR-562B/563B and Toshiba XM-3401B. This program
- is designed on CR-562B and should work well on it. If it
- can't work for you, find a better driver around.
- Yeng-Chee Su wrote the first attempt, but the program depended on
- the speed of the file-system for clean 'recordings'.
-
- The buffered read + synchronisation is added later by me.
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <dos.h>
- #include <dir.h>
- #include <string.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <io.h>
-
- #define RAW_MODE 1
- #define COOKED_MODE 0
- #define READ_MODE RAW_MODE
- #if READ_MODE == COOKED_MODE
- #define FRAME_SIZE 2048
- #else
- #define FRAME_SIZE 2352
- #endif
- #define NBLOCK 16
- #define NBUF 10
- #define SYNCH_SIZE 128 /* Bytes synch pattern */
-
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- typedef unsigned long int DWORD;
-
- struct ReqHdr {
- BYTE len;
- BYTE unit;
- BYTE command;
- WORD status;
- BYTE reserved[8];
- };
-
- struct IOCTLI {
- struct ReqHdr req;
- BYTE descriptor;
- void far *address;
- WORD len;
- WORD secnum;
- void far *ptr;
- };
-
- struct DeviceStatus {
- BYTE control;
- DWORD param;
- };
-
- struct DiskInfo {
- BYTE control;
- BYTE lowest;
- BYTE highest;
- DWORD total;
- };
-
- struct TrackInfo {
- BYTE control;
- BYTE track;
- DWORD loc;
- BYTE info;
- };
-
- struct SEEK {
- struct ReqHdr req;
- BYTE mode;
- DWORD address;
- WORD secnum;
- DWORD loc;
- };
-
- struct PlayReq {
- struct ReqHdr req;
- BYTE mode;
- DWORD loc;
- DWORD secnum;
- };
-
- int CDROM;
- int lowest, highest;
- DWORD total_time;
- char image[MAXPATH];
-
- void CallDevice(void *ptr)
- {
- static union REGS reg;
- static struct SREGS seg;
-
- segread(&seg);
- seg.es=FP_SEG(ptr);
- reg.x.ax=0x1510;
- reg.x.bx=FP_OFF(ptr);
- reg.x.cx=CDROM;
- int86x(0x2f, ®, ®, &seg);
- }
-
- int check_mscdex(void)
- {
- union REGS reg;
-
- reg.x.ax=0x1500;
- reg.x.bx=0;
- int86(0x2f, ®, ®);
- if (!reg.x.bx)
- return 0;
- else {
- CDROM=reg.x.cx;
- return 1;
- }
- }
-
- int GetDeviceStatus(void)
- {
- struct IOCTLI cmd;
- struct DeviceStatus buf;
-
- cmd.req.len=26;
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=5;
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=6;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int GetDiskInfo(void)
- {
- struct IOCTLI cmd;
- struct DiskInfo buf;
-
- cmd.req.len=26;
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=7;
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=10;
- CallDevice(&cmd);
- lowest=buf.lowest;
- highest=buf.highest;
- total_time=buf.total;
- return cmd.req.status;
- }
-
- int GetTrackInfo(int track, DWORD *loc, BYTE *info)
- {
- struct IOCTLI cmd;
- struct TrackInfo buf;
-
- cmd.req.len=26;
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=7;
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=11;
- buf.track=track;
- CallDevice(&cmd);
- *loc=buf.loc;
- *info=buf.info;
- return cmd.req.status;
- }
-
- int SeekTrack(DWORD loc)
- {
- struct SEEK cmd;
-
- cmd.req.len=24;
- cmd.req.unit=0;
- cmd.req.command=131;
- cmd.mode=1;
- cmd.address=NULL;
- cmd.secnum=0;
- cmd.loc=loc;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int PlayAudio(DWORD loc, DWORD num)
- {
- struct PlayReq cmd;
-
- cmd.req.len=22;
- cmd.req.unit=0;
- cmd.req.command=132;
- cmd.mode=1;
- cmd.loc=loc;
- cmd.secnum=num;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int StopAudio(void)
- {
- struct ReqHdr cmd;
-
- cmd.len=13;
- cmd.unit=0;
- cmd.command=133;
- CallDevice(&cmd);
- return cmd.status;
- }
-
- DWORD Red2Sierra(DWORD loc)
- {
- BYTE min, sec, frame;
-
- min = (loc >> 16) & 0xff;
- sec = (loc >> 8) & 0xff;
- frame = loc & 0xff;
- return (DWORD)min * 75 * 60 + (DWORD)sec * 75 + (DWORD)frame - 150;
- }
-
- int ReadLong(DWORD loc, WORD secnum, char far *buf)
- {
- struct ReadL {
- struct ReqHdr req;
- BYTE mode;
- void far *address;
- WORD secnum;
- DWORD loc;
- BYTE readmode;
- BYTE skip[2];
- } cmd;
-
- cmd.req.len=sizeof(cmd);
- cmd.req.unit=0;
- cmd.req.command=128;
- cmd.mode=0;
- cmd.address=buf;
- cmd.secnum=secnum;
- cmd.loc=loc;
- cmd.readmode=READ_MODE;
- cmd.skip[0]=cmd.skip[1]=0;
- CallDevice(&cmd);
- return cmd.req.status;
- }
-
- int GetVolSize(DWORD *size)
- {
- struct IOCTLI cmd;
- struct {
- BYTE control;
- DWORD size;
- } buf;
-
- cmd.req.len=sizeof(cmd);
- cmd.req.unit=0;
- cmd.req.command=3;
- cmd.descriptor=0;
- cmd.address=&buf;
- cmd.len=sizeof(buf);
- cmd.secnum=0;
- cmd.ptr=NULL;
- buf.control=8;
- CallDevice(&cmd);
- *size=buf.size;
- return cmd.req.status;
- }
-
- char *
- location_str( DWORD loc)
- {
- static char ret_buf[256];
- long min,sec,frames;
-
- frames = loc % 75;
- sec = (loc+150) / 75;
- min = sec / 60;
- sec = sec % 60;
-
- sprintf(ret_buf,"High sierra %ld ; %02ld:%02ld.%02ld",loc,min,sec,frames);
- return ret_buf;
- }
-
- void
- read_location(char *question,DWORD *loc)
- {
- #define MAX_LOC 256
- char buf[MAX_LOC],*p;
- buf[0] = '\0';
-
- while (buf[0] == '\0') {
- printf("%s",question);
- fgets(buf,MAX_LOC,stdin);
- }
- for (p=buf;*p && (*p != ':'); p++)
- ;
- if (*p == ':') {
- *loc = atol(buf)*75L*60L+atol(p+1)*75L;
- } else {
- *loc = atol(buf);
- }
- }
-
-
- void main()
- {
- WORD status;
- char *buf[NBUF],*previous_end;
- DWORD *track_loc, loc, end_pos, size;
- DWORD i, j, offset,synch_size;
- BYTE info;
- int fd, key, n,first_time;
- int retry, waveform;
- struct RIFF {
- char rID[4];
- DWORD rLen;
- } riff;
- struct FORMAT {
- char fID[4];
- DWORD fLen;
- WORD wTag;
- WORD wChannel;
- DWORD nSample;
- DWORD nByte;
- WORD align;
- WORD sample;
- };
- struct DATA {
- char dID[4];
- DWORD dLen;
- };
- struct WAVE {
- char wID[4];
- struct FORMAT fmt;
- struct DATA data;
- } wave;
-
- printf("CD-ROM digital audio data extractor, Ver 1.1\n");
- printf(" written by Yeng-Chee Su, CSIE, NCTU & Klaas Hemstra (hst@mh.nl)\n");
- printf("\n");
-
- /*
- * Allocate memory buffers
- */
- for (i=0; i< NBUF; i++)
- buf[i] = (char*)malloc((long)FRAME_SIZE * NBLOCK);
- if (buf[i] == NULL) {
- printf("Out of memory!\n");
- exit(1);
- }
- previous_end = (char*)malloc((long)FRAME_SIZE * NBLOCK);
- if (previous_end == (char *) NULL) {
- printf("Out of memory!\n");
- exit(1);
- }
-
- /*
- * Get Disc info
- */
- if (!check_mscdex()) {
- printf("No CD-ROM extension available!\n");
- exit(1);
- }
- retry=0;
- status=GetDiskInfo();
- while (status != 0x0100) {
- printf("Can't get CD-ROM information, status=%x\n", status);
- delay(1000);
- retry++;
- if (retry == 3) {
- printf("Get CD-ROM information failed\n");
- exit(1);
- }
- status=GetDiskInfo();
- }
- track_loc=(DWORD*)malloc(sizeof(DWORD)*(highest-lowest+2));
- if (track_loc==NULL) {
- printf("Out of memory!\n");
- exit(1);
- }
- track_loc = &track_loc[-lowest];
- track_loc[highest+1]=total_time;
- for (i=lowest; i<=highest; i++) {
- status=GetTrackInfo(i, &loc, &info);
- track_loc[i]=loc;
- }
- for (i=lowest; i<=highest; i++)
- printf("Track %2ld : %02ld:%02ld.%02ld %6ld Len = %ld\n", i, (track_loc[i] >> 16) & 0xff,
- (track_loc[i] >> 8) & 0xff, track_loc[i] & 0xff, Red2Sierra(track_loc[i]),
- Red2Sierra(track_loc[i+1]) - Red2Sierra(track_loc[i]));
- printf("Total time : %02ld:%02ld.%02ld\n", (total_time >> 16) & 0xff,
- (total_time >> 8) & 0xff, total_time & 0xff);
-
- /*
- * User interface
- */
- printf("Image filename:");
- gets(image);
- printf("(0) CDDA format, (1) WAV format :");
- key = getch();
- while (key != '0' && key != '1')
- key = getch();
- printf("%c\n", key);
- if (key == '1') waveform = 1; else waveform = 0;
-
- printf("(0) Read Track, (1) Read A to B :");
- key = getch();
- while (key != '0' && key != '1')
- key = getch();
- printf("%c\n", key);
- if (key == '1') {
- read_location("Start location (High sierra or min:sec) : ",&loc);
- read_location("Frame length (Sectors or min:sec) : ",&size);
- } else {
- track_again:
- printf("Which track :");
- scanf("%d", &n);
- if (n < lowest || n > highest) {
- printf("illega track!\n");
- goto track_again;
- }
- loc = Red2Sierra(track_loc[n]);
- size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
- }
- printf("Start location %s\n", location_str(loc));
- printf("Stop location %s\n", location_str(loc+size));
-
- /*
- * Create the file
- */
- _fmode = O_BINARY;
- fd = creat(image, S_IREAD|S_IWRITE);
- if (fd == -1) {
- perror("open");
- exit(1);
- }
-
- if (waveform) {
- strcpy(riff.rID, "RIFF");
- riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
- strcpy(wave.wID, "WAVE");
- strcpy(wave.fmt.fID, "fmt ");
- wave.fmt.fLen = sizeof(struct FORMAT) - 8;
- wave.fmt.wTag = 1;
- wave.fmt.wChannel = 2;
- wave.fmt.nSample = 44100L;
- wave.fmt.nByte = 44100L * 4;
- wave.fmt.align = 4;
- wave.fmt.sample = 16;
- strcpy(wave.data.dID, "data");
- wave.data.dLen = FRAME_SIZE * (DWORD)size;
- if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
- perror("write");
- exit(1);
- }
- if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
- perror("write");
- exit(1);
- }
- }
-
- /*
- * Read the date in blocks, first in memory
- */
- wave.data.dLen = 0L;
- first_time = 1;
- end_pos = loc+size;
- while (loc < end_pos) {
-
- for (i=0;(i < NBUF);i++) {
- printf("\rReading frame %ld to %ld in memory \r",
- loc, loc+NBLOCK-1);
- status = ReadLong(loc, NBLOCK, buf[i]);
- if (status != 0x0100) {
- printf("CDROM read with status %x\n", status);
- exit(1);
- }
- loc += NBLOCK;
- }
-
- if (first_time == 0) {
- /*
- * Synchronize data to previous block
- */
- offset = 0;
- synch_size = SYNCH_SIZE;
- while (offset == 0) {
- for (i=(NBLOCK/4)*FRAME_SIZE;
- i < (((unsigned int)NBLOCK*FRAME_SIZE)-synch_size);
- i+=4) {
- if (memcmp(previous_end+(NBLOCK/2)*FRAME_SIZE,buf[0]+i,synch_size) == 0) {
- if (offset == 0)
- offset = i;
- else {
- synch_size *= 2;
- if (synch_size > 4096) {
- fprintf(stderr,"Synchronisation failed, synch size to big !!\n");
- exit(1);
- }
- break;
- }
- }
- }
- if (offset == 0) {
- fprintf(stderr,"Synchronisation failed, no matching block found !!\n");
- exit(1);
- }
- }
- }
- else
- offset = 0;
-
- first_time = 0;
-
- memcpy(previous_end,buf[NBUF-1],(long)FRAME_SIZE*NBLOCK);
-
- printf("\rSynchronized write frame %ld to %ld to disk, offset = %ld ",
- loc-(NBUF*NBLOCK),loc-(NBLOCK/2),offset-(NBLOCK/2*FRAME_SIZE));
-
- for (i=0;(i < NBUF-1);i++) {
- if (write(fd, buf[i]+offset, ((long) FRAME_SIZE * NBLOCK)-offset) == -1) {
- perror("write");
- exit(1);
- }
- wave.data.dLen += (((long) FRAME_SIZE * NBLOCK)-offset);
- offset = 0;
- }
-
- /*
- * Write only half of last buffer,
- * The next loop, after synchronisation the rest will be written
- */
-
- if (write(fd, buf[NBUF-1], ((long) FRAME_SIZE * (NBLOCK/2))) == -1) {
- perror("write");
- exit(1);
- }
- wave.data.dLen += ((long) FRAME_SIZE * (NBLOCK/2));
-
- loc -= NBLOCK;
- /* sleep(1); */
- }
-
- if (waveform) {
- lseek(fd,0L,SEEK_SET);
- printf("\nCompleting header information of WAV file\n");
- riff.rLen = wave.data.dLen + sizeof(struct WAVE);
- if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
- perror("write");
- exit(1);
- }
- if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
- perror("write");
- exit(1);
- }
- }
-
- close(fd);
- free(&track_loc[lowest]);
- free(buf);
- }
-